// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const { ccclass, property } = cc._decorator;

const colorNum = 5;
const tileSize = 10;
const colors: cc.Color[] = [
    cc.Color.BLUE,
    cc.Color.CYAN,
    cc.Color.RED,
    cc.Color.GREEN,
    cc.Color.WHITE,
];
@ccclass
export default class tiles extends cc.Component {
    _editX: cc.EditBox;
    _editY: cc.EditBox;
    _tilesParent: cc.Node;
    protected onEnable(): void {
        this._editX = this.node.getChildByName('editBox_1').getComponent(cc.EditBox);
        this._editY = this.node.getChildByName('editBox_2').getComponent(cc.EditBox);
        this.node.getChildByName("crete_btn").on('click', () => {
            this.genTiles();
        })
        this._sprTemplate = this.node.getChildByName('spr-template');
        this._tilesParent = this.node.getChildByName('nodes')

        this.showColors();
    }

    _sprTemplate: cc.Node;

    showColors() {
        for (let i = 0; i < colorNum; i++) {
            let node = i == 0 ? this._sprTemplate : cc.instantiate(this._sprTemplate);
            let spr = node.getComponent(cc.Sprite);
            node.color = colors[i];
            node.parent = this._sprTemplate.parent;
            node.x += i * 100;
        }
    }

    tiles:cc.Node[][];

    // retrun hit index
    randInArr(arr:number[], probability: number) {
        let sum = 0;
        for(let i = 0;i < arr.length; i++){
            sum += arr[i];
            if(sum > 0 && probability <= sum){
                return i;
            }
        }
        cc.error('err')
        return null;
    }

    _valX:number = 0;
    _valY:number = 0;
    beforeGenTiles() {
        let valX =  parseFloat(this._editX.string)
        if(cc.js.isNumber(valX)) this._valX = valX / 100;
        let valY =  parseFloat(this._editY.string)
        if(cc.js.isNumber(valY)) this._valY = valY / 100;
        this._editX.string = (this._valX * 100).toString();
        this._editY.string = (this._valY * 100).toString();
    }

    _colorData:number[][] ;
    /**
     * 已经出现一个颜色概率超过1时，其他颜色不会出现
     * 换行时，左边没有颜色，上方颜色如果和大概率颜色不相同，上方颜色值保留，其他颜色重新分配平均概率，大概率颜色的概率也被重新分配，打破大概率独占后续颜色情况
     */
    genTiles() {
        this.beforeGenTiles();
        if(!this.tiles) {
            this.tiles = new Array(tileSize)
            for(let i = 0; i < tileSize; i++){
                this.tiles[i] =  new Array(tileSize)
                for(let j = 0;j < tileSize; j++){
                    let node = cc.instantiate(this._sprTemplate);
                    this.tiles[i][j] = node;
                    node.parent = this._tilesParent;
                    let size = this._sprTemplate.getContentSize();
                    node.setPosition(cc.v2(i * size.width * 1.2, tileSize - j * size.height * 1.2))
                }
            }
        }

        let weights:number[] = new Array(colorNum).fill(1 / colorNum);
        let colorDataArr:number[][] = this._colorData || new Array(tileSize)
        
        let hasBig = false;
        for(let i = 0; i < tileSize; i++){
            for(let j = 0;j < tileSize; j++){
                colorDataArr[j] = colorDataArr[j] || new Array(tileSize)
                // 00 初始化
                if(0 === i && 0 === j) {
                    colorDataArr[j][i] = Math.floor(Math.random() * colorNum);
                    this.tiles[j][i].color = colors[colorDataArr[j][i]]
                    continue;
                }
                // left左边颜色下标 top上方颜色下标
                let colorIdxL = colorDataArr[j - 1]?.[i];
                let colorIdxT = colorDataArr[j][i - 1];
                // 检查左方上方是否有效格子
                let hasL = cc.js.isNumber(colorIdxL);
                let hasT = cc.js.isNumber(colorIdxT);
                let addL = 0,addT = 0;
                if(hasL) {
                    addL = this._valX,addT = 0;
                    if(colorIdxL === colorIdxT){
                        // 左上颜色一样，使用Y值，hasT标为空
                        addL = this._valY,addT = 0;
                        hasT = false;
                    }else if(hasT){
                        addL = this._valX,addT = this._valX;
                    }else{
                        addL = this._valX,addT = 0;
                    }
                }else if(hasT) {
                    addL = 0,addT = this._valX;
                }else{
                    cc.error('err')
                }
                let resultL =  hasL ? weights[colorIdxL] + addL : 0;
                let resultT = hasT ? weights[colorIdxT] + addT : 0;
                let fill = (1 - resultL - resultT) / (colorNum -( (hasL && hasT) ? 2 : 1));
                weights.fill(fill)
                hasL && (weights[colorIdxL] = resultL);
                hasT && (weights[colorIdxT] = resultT);

                cc.log(j,i,weights.map((it) => it.toFixed(2)).join(','))
                // if(!hasBig && weights.find(it => it > 1)) hasBig = true;
                // if(hasBig) {
                //     if(!weights.find(it => it > 1)) {
                //         cc.error('err')
                //     }
                // }
                colorDataArr[j][i] = this.randInArr(weights,Math.random())
                this.tiles[j][i].color = colors[colorDataArr[j][i]]
            }
        }
    }
}
